﻿using System;
using System.Security.Cryptography;
using Net.Helper;
using Net.Share;
using Net.System;

namespace Net.Adapter
{
    /// <summary>
    /// 基础数据包适配器
    /// </summary>
    public class PackageAdapter : IPackageAdapter
    {
        public int HeadLength { get; set; }

        public virtual void Pack(ISegment stream)
        {
        }

        public virtual unsafe int ReadHead(ISegment stream)
        {
            var lenBytes = stream.ReadPtr(4);
            var crcCode = stream.ReadByte();//CRC检验索引
            var retVal = CRCHelper.CRC8(lenBytes, 0, 4);
            if (crcCode != retVal)
                return -1;
            var size = *(int*)lenBytes;
            if (size < 0)
                return -2;
            return size;
        }

        public virtual int Unpack(ISegment stream)
        {
            return 0;
        }
    }

    /// <summary>
    /// 使用md5校验数据部分, 并且使用随机加密法加密md5值, 这里防止md5数据重新被校验, 所以用随机加密把md5值也加密了
    /// </summary>
    public class MD5EncryptDataHeadAdapter : PackageAdapter
    {
        public int Password { get; set; } = 123456789;

        private readonly MD5 md5;

        public MD5EncryptDataHeadAdapter()
        {
            HeadLength = 16;
            md5 = MD5.Create();
        }

        public override void Pack(ISegment stream)
        {
            var retVal = md5.ComputeHash(stream.Buffer, stream.Position, stream.Count - stream.Position);
            EncryptHelper.ToEncrypt(Password, retVal);
            var len = stream.Count;
            stream.Position -= HeadLength;
            stream.Write(retVal, false);
            stream.Position = len;
        }

        public override int Unpack(ISegment stream)
        {
            var md5Hash = stream.Read(HeadLength);
            var retVal = md5.ComputeHash(stream.Buffer, stream.Position, stream.Count - stream.Position);
            EncryptHelper.ToDecrypt(Password, md5Hash, 0, HeadLength);
            for (int i = 0; i < md5Hash.Length; i++)
            {
                if (retVal[i] != md5Hash[i])
                {
                    return -1;
                }
            }
            return 0;
        }
    }

    /// <summary>
    /// 使用md5校验数据部分, 并且使用随机加密法加密数据体
    /// </summary>
    public class MD5EncryptDataBodyAdapter : PackageAdapter
    {
        public int Password { get; set; } = 123456789;

        private readonly MD5 md5;

        public MD5EncryptDataBodyAdapter()
        {
            HeadLength = 16;
            md5 = MD5.Create();
        }

        public override void Pack(ISegment stream)
        {
            var retVal = md5.ComputeHash(stream.Buffer, stream.Position, stream.Count - stream.Position);
            EncryptHelper.ToEncrypt(Password, stream.Buffer, stream.Position, stream.Count - stream.Position);
            var len = stream.Count;
            stream.Position -= HeadLength;
            stream.Write(retVal, false);
            stream.Position = len;
        }

        public override int Unpack(ISegment stream)
        {
            var md5Hash = stream.Read(HeadLength);
            EncryptHelper.ToDecrypt(Password, stream.Buffer, stream.Position, stream.Count - stream.Position);
            var retVal = md5.ComputeHash(stream.Buffer, stream.Position, stream.Count - stream.Position);
            for (int i = 0; i < md5Hash.Length; i++)
            {
                if (retVal[i] != md5Hash[i])
                {
                    return -1;
                }
            }
            return 0;
        }
    }

    /// <summary>
    /// 使用随机加密法加密数据体
    /// </summary>
    public class EncryptDataBodyAdapter : PackageAdapter
    {
        public int Password { get; set; } = 123456789;

        public override void Pack(ISegment stream)
        {
            EncryptHelper.ToEncrypt(Password, stream.Buffer, stream.Position, stream.Count - stream.Position);
        }

        public override int Unpack(ISegment stream)
        {
            EncryptHelper.ToDecrypt(Password, stream.Buffer, stream.Position, stream.Count - stream.Position);
            return 0;
        }
    }
}
